import { render, createVNode } from 'vue'
import * as Cesium from 'cesium'
/**
 * html简单文本标注类
 */
class HtmlMarker {
  constructor(viewer, options) {
    this.viewer = viewer
    this.position = Cesium.defaultValue(options.position, Cesium.Cartesian3.ZERO)
    this.isShow = Cesium.defaultValue(options.isShow, true)
    this.scaleByDistance = Cesium.defaultValue(options.scaleByDistance, new Cesium.NearFarScalar(1000, 1, 20000, 0.4))
    this.popupType = Cesium.defaultValue(options.type, 'marker')
    this.offset = Cesium.defaultValue(options.offset, [0, 0])
    this.popupRoutes = {
      marker: () => import('./Popup.vue'),
    }
    this.queryPopup = null
    this.isDisplay = true
  }

  // 外部修改坐标
  changePosition(position) {
    this.position = position
  }

  removeQueryPopup() {
    this.queryPopup && this.queryPopup.removeMarker()
  }

  //主要功能：将 Vue 组件以 DOM 形式添加到 Cesium 地图上。
  // 异步加载 Popup.vue 组件；
  // 创建一个虚拟节点 this.vmInstance；
  // 渲染并挂载到 Cesium 的 DOM 容器上；
  // 添加 postRender 事件，用于每帧更新位置；
  // 控制显示/隐藏。

  async addLabel(houseInfo) {
    // 如果在模板中找不到对应的，直接返回
    if (!this.popupRoutes[this.popupType]) {
      return null
    }
    const res = await this.popupRoutes[this.popupType]()
    this.vmInstance = createVNode(res.default, {
      houseInfo: houseInfo,
      closePopup: () => {
        this.removeMarker()
      },
    }) //根据模板创建一个面板
    this.mountNode = document.createElement('div')
    render(this.vmInstance, this.mountNode)
    this.viewer.cesiumWidget.container.appendChild(this.mountNode) //将字符串模板生成的内容添加到DOM上
    this.addPostRender()
    this.vmInstance.el.style.display = this.isShow ? 'block' : 'none'
    return this.vmInstance.el
  }

  //根据当前相机高度 curValue 以及传入的 NearFarScalar，计算缩放比例，实现“近大远小”。
  // calcaluteGrade(curValue, stdNearFar) {
  //   let curPara = -1
  //   if (curValue <= stdNearFar.near) {
  //     curPara = stdNearFar.nearValue
  //   } else if (curValue >= stdNearFar.far) {
  //     curPara = stdNearFar.farValue
  //   } else {
  //     const totalGrade = Math.ceil(Math.log(stdNearFar.far / stdNearFar.near) / Math.log(2))
  //     const curGrade = Math.round(Math.log(curValue / stdNearFar.near) / Math.log(2))
  //     curPara = stdNearFar.nearValue + ((stdNearFar.farValue - stdNearFar.nearValue) * curGrade) / totalGrade
  //   }
  //   return curPara
  // }

  //绑定 Cesium 的 postRender 场景渲染事件，它会在每一帧渲染完成后触发,用于在每帧渲染后更新标注位置。
  addPostRender() {
    this.viewer.scene.postRender.addEventListener(this.postRender, this)
  }

  //场景渲染事件 实时更新标签的位置 使其与笛卡尔坐标一致
  postRender() {
    if (!this.vmInstance.el || !this.vmInstance.el.style) return
    const canvasHeight = this.viewer.scene.canvas.height
    const windowPosition = new Cesium.Cartesian2()
    // 调整popup实例的位置
    Cesium.SceneTransforms.wgs84ToWindowCoordinates(this.viewer.scene, this.position, windowPosition)
    this.vmInstance.el.style.bottom = canvasHeight - windowPosition.y + this.offset[1] + 'px'
    const elWidth = this.vmInstance.el.offsetWidth
    this.vmInstance.el.style.left = windowPosition.x - elWidth / 2 + this.offset[0] + 'px'

    // 处理近大远小效果
    // const cameraHeight = Math.ceil(this.viewer.camera.positionCartographic.height)
    // const scaleSize = this.calcaluteGrade(cameraHeight, this.scaleByDistance)
    // this.vmInstance.el.style.transform = `scale(${scaleSize},${scaleSize})`

    // 只有当显示模式打开的时候，才进行优化
    if (this.isDisplay) {
      const condition1 = windowPosition.y < 0 || windowPosition.y > canvasHeight
      const condition2 = this.viewer.camera.positionCartographic.height > 12000
      const condition3 = windowPosition.x < 0 || windowPosition.x > this.viewer.scene.canvas.width
      if (condition1 || condition2 || condition3) {
        this.vmInstance.el.style.display = 'none'
      } else {
        this.vmInstance.el.style.display = 'block'
      }
    }
  }

  //清理操作：
  // 从 Cesium 容器中移除挂载的 DOM；
  // 移除事件监听；
  // 清空引用。
  removeMarker() {
    this.mountNode && this.viewer.cesiumWidget.container.removeChild(this.mountNode) //删除DOM
    this.viewer.scene.postRender.removeEventListener(this.postRender, this) //移除事件监听
    this.mountNode = null
  }
}
export default HtmlMarker
